package model.persistence.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import model.persistence.AbstractDAO;

import model.business.Interno;
import model.business.InternoImpl;
import model.persistence.InternoDAO;

public class PostgresInternoDAO extends AbstractDAO implements InternoDAO {

    public Object insert(Object dto) throws SQLException {
        if (!(dto instanceof Interno)) //se algo que nao seja Interno
        {
            throw new SQLException("Tipo de dado inválido para cadastro no banco de dados");
        }

        Interno interno = (Interno) dto;

        Connection connection = this.getConnection();
        PreparedStatement statement = null;
        ResultSet resultSet = null;

        try {
            statement = connection.prepareStatement("INSERT INTO INTERNO (NOME, CPF, RG, CTPS, DATA_NASCIMENTO, SEXO, TEMPO_PENA, ACESSO_USUARIO, DATA_CADASTRO, DATA_ENTRADA, DATA_SAIDA_PREVISAO, DATA_SAIDA_FINAL, SIT_ESTUDANTE, SIT_TRABALHADOR, SITUACAO, CELA_CELA) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?);"); //prepareStatement - executa comandos SQL, ? separadas por virgula
            statement.setString(1, interno.getNome());
            statement.setString(2, interno.getCpf());
            statement.setString(3, interno.getRg());
            statement.setString(4, interno.getCtps());
            statement.setString(5, interno.getData_nascimento());
            statement.setString(6, interno.getSexo());
            statement.setInt(7, interno.getTempo_pena());
            statement.setString(8, interno.getAcesso_usuario());
            statement.setString(9, interno.getData_cadastro());
            statement.setString(10, interno.getData_entrada());
            statement.setString(11, interno.getData_saida_previsao());
            statement.setString(12, interno.getData_saida_final());
            statement.setString(13, interno.getSit_estudante());
            statement.setString(14, interno.getSit_trabalhador());
            statement.setString(15, interno.getSituacao());
            statement.setString(16, interno.getCela_cela());
            statement.execute();

            statement = connection.prepareStatement("SELECT * FROM INTERNO WHERE NOME = ? AND CPF = ? AND RG = ? AND CTPS = ? AND DATA_NASCIMENTO = ? AND SEXO = ? AND TEMPO_PENA = ? AND ACESSO_USUARIO = ? AND DATA_CADASTRO = ? AND DATA_ENTRADA = ? AND DATA_SAIDA_PREVISAO = ? AND DATA_SAIDA_FINAL = ? AND SIT_ESTUDANTE = ? AND SIT_TRABALHADOR = ? AND SITUACAO = ? AND CELA_CELA = ?");
            statement.setString(1, interno.getNome());
            statement.setString(2, interno.getCpf());
            statement.setString(3, interno.getRg());
            statement.setString(4, interno.getCtps());
            statement.setString(5, interno.getData_nascimento());
            statement.setString(6, interno.getSexo());
            statement.setInt(7, interno.getTempo_pena());
            statement.setString(8, interno.getAcesso_usuario());
            statement.setString(9, interno.getData_cadastro());
            statement.setString(10, interno.getData_entrada());
            statement.setString(11, interno.getData_saida_previsao());
            statement.setString(12, interno.getData_saida_final());
            statement.setString(13, interno.getSit_estudante());
            statement.setString(14, interno.getSit_trabalhador());
            statement.setString(15, interno.getSituacao());
            statement.setString(16, interno.getCela_cela());

            resultSet = statement.executeQuery();//traz o q esta no cache do banco pra voce
            resultSet.next();

            interno = new InternoImpl(resultSet.getInt("ID"), resultSet.getString("NOME"), resultSet.getString("CPF"), resultSet.getString("RG"), resultSet.getString("CTPS"), resultSet.getString("DATA_NASCIMENTO"), resultSet.getString("SEXO"), resultSet.getInt("TEMPO_PENA"), resultSet.getString("ACESSO_USUARIO"), resultSet.getString("DATA_CADASTRO"), resultSet.getString("DATA_ENTRADA"), resultSet.getString("DATA_SAIDA_PREVISAO"), resultSet.getString("DATA_SAIDA_FINAL"), resultSet.getString("SIT_ESTUDANTE"), resultSet.getString("SIT_TRABALHADOR"), resultSet.getString("SITUACAO"), resultSet.getString("CELA_CELA"));

        } catch (SQLException erroBD) {
            throw new SQLException("Não foi possível cadastrar o Interno. \n Motivo:  \n" + erroBD.getMessage());
        } finally {
            if (statement != null) {
                statement.close();
            }
        }
        return interno;
    }

    public Object update(Object dto) throws SQLException {
        if (!(dto instanceof Interno)) //se algo que nao seja Interno
        {
            throw new SQLException("Tipo de dado inválido para cadastro no banco de dados");
        }

        Interno interno = (Interno) dto;

        Connection connection = this.getConnection();
        PreparedStatement statement = null;

        try {
            statement = connection.prepareStatement("UPDATE INTERNO SET NOME = ?, CPF = ?, RG = ?, CTPS = ?, DATA_NASCIMENTO = ?, SEXO = ?, TEMPO_PENA = ?, ACESSO_USUARIO = ?, DATA_CADASTRO = ?, DATA_ENTRADA = ?, DATA_SAIDA_PREVISAO = ?, DATA_SAIDA_FINAL = ?, SIT_ESTUDANTE = ?, SIT_TRABALHADOR = ?, SITUACAO = ?, CELA_CELA = ? WHERE ID = ?;");
            statement.setString(1, interno.getNome());
            statement.setString(2, interno.getCpf());
            statement.setString(3, interno.getRg());
            statement.setString(4, interno.getCtps());
            statement.setString(5, interno.getData_nascimento());
            statement.setString(6, interno.getSexo());
            statement.setInt(7, interno.getTempo_pena());
            statement.setString(8, interno.getAcesso_usuario());
            statement.setString(9, interno.getData_cadastro());
            statement.setString(10, interno.getData_entrada());
            statement.setString(11, interno.getData_saida_previsao());
            statement.setString(12, interno.getData_saida_final());
            statement.setString(13, interno.getSit_estudante());
            statement.setString(14, interno.getSit_trabalhador());
            statement.setString(15, interno.getSituacao());
            statement.setString(16, interno.getCela_cela());

            int oid = ((Integer) interno.getOID()).intValue();
            statement.setInt(17, oid);
            statement.execute();

        } catch (SQLException erroBD) {
            throw new SQLException("Não foi possível alterar o Interno. \n Motivo: " + erroBD.getMessage());
        } finally {
            if (statement != null) {
                statement.close();
            }
        }
        return interno;
    }

    public void delete(Object dto) throws SQLException {
        if (!(dto instanceof Interno)) //se algo que nao seja Interno
        {
            throw new SQLException("Tipo de dado inválido para cadastro no banco de dados");
        }

        Interno interno = (Interno) dto;

        Connection connection = this.getConnection();
        PreparedStatement statement = null;

        try {
            statement = connection.prepareStatement("DELETE FROM INTERNO WHERE ID = ?;");

            int oid = ((Integer) interno.getOID()).intValue();
            statement.setInt(1, oid);
            statement.execute();

        } catch (SQLException erroBD) {
            throw new SQLException("Não foi possível excluir o Interno. \n Motivo: " + erroBD.getMessage());
        } finally {
            if (statement != null) {
                statement.close();
            }
        }
    }

    public Object find(Object oid) throws SQLException {
        if (!(oid instanceof Integer)) {
            throw new SQLException("ID não é um número inteiro.");
        }
        int idlogin = ((Integer) oid).intValue();
        Connection connection = this.getConnection();
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        Interno interno = null; //posso criar tambem InternoImpl interno
        try {
            statement = connection.prepareStatement("SELECT * FROM INTERNO WHERE ID = ?;");
            statement.setInt(1, idlogin);
            resultSet = statement.executeQuery();
            if (!resultSet.next()) {
                throw new SQLException("Não existe Interno com idlogin = " + idlogin);
            }
            interno = new InternoImpl(resultSet.getInt("ID"), resultSet.getString("NOME"), resultSet.getString("CPF"), resultSet.getString("RG"), resultSet.getString("CTPS"), resultSet.getString("DATA_NASCIMENTO"), resultSet.getString("SEXO"), resultSet.getInt("TEMPO_PENA"), resultSet.getString("ACESSO_USUARIO"), resultSet.getString("DATA_CADASTRO"), resultSet.getString("DATA_ENTRADA"), resultSet.getString("DATA_SAIDA_PREVISAO"), resultSet.getString("DATA_SAIDA_FINAL"), resultSet.getString("SIT_ESTUDANTE"), resultSet.getString("SIT_TRABALHADOR"), resultSet.getString("SITUACAO"), resultSet.getString("CELA_CELA"));

        } catch (SQLException erroBD) {
            throw new SQLException("Não foi possível encontrar o Interno \n Motivo: " + erroBD.getMessage());
        } finally {
            if (resultSet != null) {
                resultSet.close();
            }
            if (statement != null) {
                statement.close();
            }
        }
        return interno;
    }

    @Override
    public List<Interno> findInternos(String situacao) throws SQLException {

        Connection connection = this.getConnection();
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        List<Interno> internos = new ArrayList<Interno>();
        try {
            statement = connection.prepareStatement("SELECT * FROM INTERNO WHERE situacao = ?");
            statement.setString(1, situacao);
            resultSet = statement.executeQuery();

            //Enquanto tiver proximo ele monta a lista
            if (!resultSet.next()) {


                throw new SQLException("Não existe Internos ativos");
            } else {
                Interno interno = new InternoImpl(resultSet.getInt("ID"), resultSet.getString("NOME"), resultSet.getString("CPF"), resultSet.getString("RG"), resultSet.getString("CTPS"), resultSet.getString("DATA_NASCIMENTO"), resultSet.getString("SEXO"), resultSet.getInt("TEMPO_PENA"), resultSet.getString("ACESSO_USUARIO"), resultSet.getString("DATA_CADASTRO"), resultSet.getString("DATA_ENTRADA"), resultSet.getString("DATA_SAIDA_PREVISAO"), resultSet.getString("DATA_SAIDA_FINAL"), resultSet.getString("SIT_ESTUDANTE"), resultSet.getString("SIT_TRABALHADOR"), resultSet.getString("SITUACAO"), resultSet.getString("CELA_CELA"));
                internos.add(interno);

                while (resultSet.next()) {
                    interno = new InternoImpl(resultSet.getInt("ID"), resultSet.getString("NOME"), resultSet.getString("CPF"), resultSet.getString("RG"), resultSet.getString("CTPS"), resultSet.getString("DATA_NASCIMENTO"), resultSet.getString("SEXO"), resultSet.getInt("TEMPO_PENA"), resultSet.getString("ACESSO_USUARIO"), resultSet.getString("DATA_CADASTRO"), resultSet.getString("DATA_ENTRADA"), resultSet.getString("DATA_SAIDA_PREVISAO"), resultSet.getString("DATA_SAIDA_FINAL"), resultSet.getString("SIT_ESTUDANTE"), resultSet.getString("SIT_TRABALHADOR"), resultSet.getString("SITUACAO"), resultSet.getString("CELA_CELA"));
                    internos.add(interno);
                }
            }

        } catch (SQLException erroBD) {
            throw new SQLException("Não foi possível encontrar o Interno \n Motivo: " + erroBD.getMessage());
        } finally {
            if (resultSet != null) {
                resultSet.close();
            }
            if (statement != null) {
                statement.close();
            }
        }
        return internos;
    }
}
